using System;
using System.IO;
using System.Globalization;
using System.Collections.Generic;

namespace MonsterNet
{
	/// <summary>
	/// http://stackoverflow.com/questions/128618/c-file-size-format-provider
	/// </summary>
	struct FileSize : IFormattable
	{
	    private ulong _value;

	    private const int DEFAULT_PRECISION = 2;

	    private static IList<string> Units;
	
	    static FileSize()
	    {
	        Units = new List<string>(){
	            "B", "KB", "MB", "GB", "TB"
	        };
	    }
	
	    public FileSize(ulong value)
	    {
	        _value = value;
	    }
	
	    public static explicit operator FileSize(ulong value)
	    {
	        return new FileSize(value);
	    }
	
	    override public string ToString()
	    {
	        return ToString(null, null);
	    }
	
	    public string ToString(string format)
	    {
	        return ToString(format, null);
	    }
	
	    public string ToString(string format, IFormatProvider formatProvider)
	    {
	        int precision;
	
	        if (String.IsNullOrEmpty(format))
	            return ToString(DEFAULT_PRECISION);
	        else if (int.TryParse(format, out precision))
	            return ToString(precision);
	        else
	            return _value.ToString(format, formatProvider);
	    }
	
	    /// <summary>
	    /// Formats the FileSize using the given number of decimals.
	    /// </summary>
	    public string ToString(int precision)
	    {
	        double pow = Math.Floor((_value > 0 ? Math.Log(_value) : 0) / Math.Log(1024));
	        pow = Math.Min(pow, Units.Count - 1);
	        double value = (double)_value / Math.Pow(1024, pow);
	        return value.ToString(pow == 0 ? "F0" : "F" + precision.ToString()) + " " + Units[(int)pow];
	    }
	}
	
	abstract public class MNGlobal
	{
		public const string kMonsterNETFileExtension = @".MonsterNET";
		public const string kDefaultContentsFileName = @"Contents.MonsterNET";
		
		public static string CombinePathAndFilename(string path, string filename)
		{
			string filenameWithSeparator = filename;
			
			if (!filename.StartsWith(Path.DirectorySeparatorChar.ToString()))
			{
				filenameWithSeparator = Path.Combine(Path.DirectorySeparatorChar.ToString(), filenameWithSeparator);
			}					
			
			return path + filenameWithSeparator;					
		}		
		
		public static string DefaultDirectoryWithFilename(string filename)
		{
			return CombinePathAndFilename(DefaultDirectory(),filename);
		}
		
		public static string DefaultDirectory()
		{
			string AppDataDirectory;

			AppDataDirectory = Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
		
			AppDataDirectory += Path.Combine(Path.DirectorySeparatorChar.ToString(), "MonsterNet");

			return AppDataDirectory;
		}
		
		public static bool CreateDefaultDirectory()
		{
			try
			{
				Directory.CreateDirectory(MNGlobal.DefaultDirectory());
			}
			catch
			{
			}
			
			if (Directory.Exists(MNGlobal.DefaultDirectory()))
			{
				Console.WriteLine(MNGlobal.DefaultDirectory());
				return true; 
			} 
			else 
			{
				return false; 
			}
		}
		
        public static string CreateRootlessPath(string path, string rootPath)
        {
			string result = string.Empty;
			
			if(path != rootPath) {
            	if (path.StartsWith(rootPath)) {   
					result = path.Substring(rootPath.Length); 
				} else {   
					result = path; 
				}
				//make sure the result doesn't start with a DirectorySeparatorChar
				if(result.StartsWith(Path.DirectorySeparatorChar.ToString())) {
					result = result.Substring(Path.DirectorySeparatorChar.ToString().Length);
				}
			} else {
				result = string.Empty;
			}
			return result;
        }		
		
		public static string GetSizeFromUlongToString(double sizeInBytes)
		{
			return new FileSize((ulong)sizeInBytes).ToString();
		}
		
		public static string GetNameOfLocation(MNFSObjectLocation location) {
			string result = string.Empty;
			// TODO: user configurable results?
			switch (location) {
			case MNFSObjectLocation.Destination:
				result = @"Your Files";
				break;
			case MNFSObjectLocation.Portable:
				result = @"Portable Device";
				break;
			case MNFSObjectLocation.Source:
				result = @"Source Files";
				break;
			default:
				result = string.Format(@"UNKNOWN LOCATION: {0}", (int)location);
				break;
			}
			
			return result;
		}
		
		public static bool IsUnix() {
			int p = (int) Environment.OSVersion.Platform;
                if ((p == 4) || (p == 6) || (p == 128)) {
                        return true;
                } else {
                        return false;
                }
		}
		
	}
}

